﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Xiezl.Common.LinqEx;
/*
 * 作者: 谢中涞,博客园:http://www.cnblogs.com/xie-zhonglai
 * 欢迎转载,但请保留出处
 * */
namespace Xiezl.Common.EFExpressions
{
    /// <summary>
    /// 构建一个between条件
    /// </summary>
    public class BetweenEFExpression<T, TVal> : EFExpression<T> where T : class
    {
        /// <summary>
        /// 定义条件的实体属性
        /// </summary>
        private Expression<Func<T, TVal>> property;
        private TVal from;
        private TVal to;


        /// <summary>
        /// 实例化新的between条件
        /// </summary>
        /// <param name="property"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        public BetweenEFExpression(Expression<Func<T, TVal>> property, TVal from, TVal to)
        {
            if (property == null)
                throw new ArgumentNullException("property");
            this.property = property;
            this.from = from;
            this.to = to;
        }

        public override Expression<Func<T, bool>> GetExpression()
        {
            Expression<Func<T, bool>> exp = null;

            var candidateExp = Expression.Parameter(typeof(T), "x");
            if (Expression != null)
                exp = Expression.Lambda<Func<T, bool>>(Expression, candidateExp);

            return exp;
        }

        internal override Expression Expression
        {
            get
            {
                if (_Expression == null)
                {
                    Type type = typeof(TVal);
                    var constantFrom = Expression.Constant(from);
                    var constantTo = Expression.Constant(to);

                    var propertyBody = GetMemberExpression(this, property);

                    Expression nonNullProperty = propertyBody;

                    //如果是Nullable<X>类型，则转化成X类型
                    if (type.IsNullableType())
                    {
                        type = type.GetNonNullableType();
                        nonNullProperty = Expression.Convert(propertyBody, type);
                    }
                    var fromExp = Expression.GreaterThanOrEqual(nonNullProperty, constantFrom);
                    var toExp = Expression.LessThanOrEqual(nonNullProperty, constantTo);
                    var tempExp = Expression.AndAlso(fromExp, toExp);
                    _Expression = tempExp;
                }
                return _Expression;
            }
        }
    }
}
